﻿Imports System
Imports System.Collections.Generic
Imports System.Reflection

Namespace System.Workflow.ComponentModel
    Friend Class PathWalker
        ' Methods
        Private Shared Function PopulateMembers(ByVal type As Type, ByVal memberName As String) As MemberInfo()
            Dim list As New List([Of] MemberInfo)
            list.AddRange(type.GetMember(memberName, (MemberTypes.Property Or (MemberTypes.Method Or (MemberTypes.Field Or MemberTypes.Event))), (BindingFlags.FlattenHierarchy Or (BindingFlags.Public Or (BindingFlags.Static Or BindingFlags.Instance)))))
            If type.IsInterface Then
                Dim type2 As Type
                For Each type2 In type.GetInterfaces
                    list.AddRange(type2.GetMember(memberName, (MemberTypes.Property Or (MemberTypes.Method Or (MemberTypes.Field Or MemberTypes.Event))), (BindingFlags.FlattenHierarchy Or (BindingFlags.Public Or (BindingFlags.Static Or BindingFlags.Instance)))))
                Next
            End If
            Return list.ToArray
        End Function

        Public Function TryWalkPropertyPath(ByVal rootType As Type, ByVal path As String) As Boolean
            If (rootType Is Nothing) Then
                Throw New ArgumentNullException("rootType")
            End If
            If String.IsNullOrEmpty(path) Then
                Throw New ArgumentNullException("path")
            End If
            Dim type As Type = rootType
            Dim currentPath As String = String.Empty
            Dim parser As New PathParser
            Dim list As List([Of] SourceValueInfo) = parser.Parse(path, True)
            Dim error As String = parser.Error
            Dim i As Integer
            For i = 0 To list.Count - 1
                Dim infoArray As MemberInfo()
                Dim info7 As PropertyInfo
                Dim args5 As PathMemberInfoEventArgs
                Dim info As SourceValueInfo = list.Item(i)
                If String.IsNullOrEmpty(info.name) Then
                    If (Not Me.PathErrorFound Is Nothing) Then
                        Me.PathErrorFound.Invoke(Me, New PathErrorInfoEventArgs(info, currentPath))
                    End If
                    Return False
                End If
                Dim str3 As String = If((info.type = SourceValueType.Property), info.name, ("[" & info.name & "]"))
                Dim str4 As String = If(String.IsNullOrEmpty(currentPath), str3, (currentPath & If((info.type = SourceValueType.Property), ".", String.Empty) & str3))
                Dim propertyType As Type = Nothing
                Dim memberInfo As MemberInfo = Nothing
                Select Case info.type
                    Case SourceValueType.Property
                        infoArray = PathWalker.PopulateMembers(type, info.name)
                        If (((Not infoArray Is Nothing) AndAlso (infoArray.Length <> 0)) AndAlso (Not infoArray(0) Is Nothing)) Then
                            Exit Select
                        End If
                        If (Not Me.PathErrorFound Is Nothing) Then
                            Me.PathErrorFound.Invoke(Me, New PathErrorInfoEventArgs(info, currentPath))
                        End If
                        Return False
                    Case SourceValueType.Indexer
                        If String.IsNullOrEmpty(info.name) Then
                            goto Label_0494
                        End If
                        Dim aryArgName As String() = info.name.Split(New Char() { ","c })
                        Dim objArray2 As Object() = New Object(aryArgName.Length  - 1) {}
                        info7 = BindHelpers.GetMatchedPropertyInfo(type, aryArgName, objArray2)
                        If (info7 Is Nothing) Then
                            goto Label_0476
                        End If
                        If (Me.MemberFound Is Nothing) Then
                            goto Label_0459
                        End If
                        args5 = New PathMemberInfoEventArgs(str4, type, info7, PathMemberKind.Index, (i = (list.Count - 1)), objArray2)
                        Me.MemberFound.Invoke(Me, args5)
                        If (args5.Action <> PathWalkAction.Cancel) Then
                            goto Label_044D
                        End If
                        Return False
                    Case Else
                        goto Label_04B2
                End Select
                memberInfo = infoArray(0)
                If (TypeOf memberInfo Is EventInfo OrElse TypeOf memberInfo Is MethodInfo) Then
                    If (Not Me.MemberFound Is Nothing) Then
                        Dim e As New PathMemberInfoEventArgs(str4, type, memberInfo, PathMemberKind.Event, (i = (list.Count - 1)))
                        Me.MemberFound.Invoke(Me, e)
                        If (e.Action = PathWalkAction.Cancel) Then
                            Return False
                        End If
                        If (e.Action = PathWalkAction.Stop) Then
                            Return True
                        End If
                    End If
                    Return String.IsNullOrEmpty([error])
                End If
                If TypeOf memberInfo Is PropertyInfo Then
                    Dim originalPropertyInfo As PropertyInfo = [TryCast](memberInfo,PropertyInfo)
                    Dim getMethod As MethodInfo = originalPropertyInfo.GetGetMethod
                    Dim setMethod As MethodInfo = originalPropertyInfo.GetSetMethod
                    Dim info6 As New ActivityBindPropertyInfo(type, getMethod, setMethod, originalPropertyInfo.Name, originalPropertyInfo)
                    propertyType = info6.PropertyType
                    If (info6.GetIndexParameters.Length <= 0) Then
                        If (Not Me.MemberFound Is Nothing) Then
                            Dim args3 As New PathMemberInfoEventArgs(str4, type, info6, PathMemberKind.Property, (i = (list.Count - 1)))
                            Me.MemberFound.Invoke(Me, args3)
                            If (args3.Action = PathWalkAction.Cancel) Then
                                Return False
                            End If
                            If (args3.Action = PathWalkAction.Stop) Then
                                Return True
                            End If
                        End If
                    Else
                        If (((i >= (list.Count - 1)) OrElse (list.Item((i + 1)).type <> SourceValueType.Indexer)) OrElse String.IsNullOrEmpty(list.Item((i + 1)).name)) Then
                            If (Not Me.PathErrorFound Is Nothing) Then
                                Me.PathErrorFound.Invoke(Me, New PathErrorInfoEventArgs(info, currentPath))
                            End If
                            Return False
                        End If
                        Dim argNames As String() = list.Item((i + 1)).name.Split(New Char() { ","c })
                        Dim args As Object() = New Object(argNames.Length  - 1) {}
                        If Not BindHelpers.MatchIndexerParameters(info6, argNames, args) Then
                            If (Not Me.PathErrorFound Is Nothing) Then
                                Me.PathErrorFound.Invoke(Me, New PathErrorInfoEventArgs(info, currentPath))
                            End If
                            Return False
                        End If
                        str4 = (str4 & "[" & list.Item((i + 1)).name & "]")
                        If (Not Me.MemberFound Is Nothing) Then
                            Dim args2 As New PathMemberInfoEventArgs(str4, type, info6, PathMemberKind.IndexedProperty, (i = (list.Count - 2)), args)
                            Me.MemberFound.Invoke(Me, args2)
                            If (args2.Action = PathWalkAction.Cancel) Then
                                Return False
                            End If
                            If (args2.Action = PathWalkAction.Stop) Then
                                Return True
                            End If
                        End If
                        i += 1
                    End If
                Else
                    If (Not Me.MemberFound Is Nothing) Then
                        Dim args4 As New PathMemberInfoEventArgs(str4, type, memberInfo, PathMemberKind.Field, (i = (list.Count - 1)))
                        Me.MemberFound.Invoke(Me, args4)
                        If (args4.Action = PathWalkAction.Cancel) Then
                            Return False
                        End If
                        If (args4.Action = PathWalkAction.Stop) Then
                            Return True
                        End If
                    End If
                    propertyType = [TryCast](memberInfo,FieldInfo).FieldType
                End If
                goto Label_04B2
            Label_044D:
                If (args5.Action = PathWalkAction.Stop) Then
                    Return True
                End If
            Label_0459:
                propertyType = info7.PropertyType
                If (propertyType Is Nothing) Then
                    propertyType = info7.GetGetMethod.ReturnType
                End If
                goto Label_04B2
            Label_0476:
                If (Not Me.PathErrorFound Is Nothing) Then
                    Me.PathErrorFound.Invoke(Me, New PathErrorInfoEventArgs(info, currentPath))
                End If
                Return False
            Label_0494:
                If (Not Me.PathErrorFound Is Nothing) Then
                    Me.PathErrorFound.Invoke(Me, New PathErrorInfoEventArgs(info, currentPath))
                End If
                Return False
            Label_04B2:
                type = propertyType
                currentPath = str4
            Next i
            Return String.IsNullOrEmpty([error])
        End Function


        ' Fields
        Public MemberFound As EventHandler([Of] PathMemberInfoEventArgs)
        Public PathErrorFound As EventHandler([Of] PathErrorInfoEventArgs)
    End Class
End Namespace

